<?php
abstract class Command{
    abstract function execute(CommandContext $context);
}

class LoginCommand extends Command{
    public function execute(CommandContext $context)
    {
        $manager = Registry::getAccessManger();
        $user = $context->get('username');
        $pass = $context->get('pass');
        $user_obj = $manager->login($user,$pass);
        if(is_null($user_obj)){
            $context->setError($manager->getError());
            return false;
        }
        $context->addParam('user',$user_obj);
    }
}

class CommandContext{
    private $params = array();
    private $error = '';

    function __construct()
    {
        $this->params = $_REQUEST;
    }

    function addParam($key,$val){
        $this->params[$key] = $val;
    }

    function get($key){
        return $this->params[$key];
    }

    function setError($error){
        $this->error = $error;
    }

    function getError(){
        return $this->error;
    }
}

class CommandNotFoundException extends Exception{}

class CommandFactory{
    private static $dir = 'commands';

    static function getCommand($action = 'default'){
        if(preg_match('/\w/',$action)){
            throw new Exception();
        }
        $class = ucfirst(strtolower($action)).'Command';
        $file = self::$dir.DIRECTORY_SEPARATOR."{$class}.php";
        if(!file_exists($file)){
            throw new CommandNotFoundException('文件未找到');
        }
        require_once($file);
        if(!class_exists($class)){
            throw new CommandNotFoundException('类未找到');
        }
        $cmd = new $class();
        return $cmd;
    }
}

class Controller{
    private $context;
    function __construct()
    {
        $this->context = new CommandContext();
    }

    function getContext(){
        return $this->context;
    }

    function process(){
        $cmd = CommandFactory::getCommand($this->context->get('action'));
        if(!$cmd->excute($this->context)){
            // 处理失败
        }else{
            //处理成功
            //分发试图
        }
    }
}

$controller = new Controller();
$context = $controller->getContext();
$context = addParam('action','login');
$context = addParam('user','zhangsan');
$context = addParam('pass','123456');
$controller->process();

class FeedBackCommand extends Command{
    public function execute(CommandContext $context)
    {
        $msgSystem = Registry::getMessageSystem();
        $email = $context->get('email');
        $msg = $context->get('msg');
        $topic = $context->get('topic');
        $result = $msgSystem->send($email,$msg,$topic);
        if(!$result){
            $context->setError($msgSystem->getError());
            return false;
        }
        return true;
    }
}